﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DalGen.Enum;
using MySql.Data.MySqlClient;
using System.Data;
using DalGen.Contracts;
using NVelocity.App;
using NVelocity;
using Commons.Collections;
using NVelocity.Runtime;
using DalGen.Entity;
using System.IO;
using System.Xml;
using DalGen.Common;


namespace DalGen.Service
{
    public class MySqlBuilder : BuilderBase, IBuilder
    {
        protected MySqlConnection _conn;

        public EProjectInfo ProjectInfo { get; set; }


        public MySqlBuilder()
        {
            string sSplit = System.AppDomain.CurrentDomain.BaseDirectory.Substring(System.AppDomain.CurrentDomain.BaseDirectory.Length - 1);
            string ConfigPath;
            if (sSplit != @"\" && sSplit != "/")
                ConfigPath = System.AppDomain.CurrentDomain.BaseDirectory + @"\";
            else
                ConfigPath = System.AppDomain.CurrentDomain.BaseDirectory;
            string sConfigFileName = ConfigPath + @"Reflection\MySQL2DotNet.xml";
            domSql2DotNet = new XmlDocument();
            domSql2DotNet.Load(sConfigFileName);

        }


        public MySqlConnection GetConn()
        {
            ConnectionString = string.Format("Server={0};Port={1};DataBase={2};Password={3};User ID={4}", ProjectInfo.Server, ProjectInfo.Port, ProjectInfo.DataBaseName, ProjectInfo.Pwd, ProjectInfo.UID);

            var _sqlcon = new MySqlConnection(ConnectionString);

            return _sqlcon;
        }


        public void ConnectToDB()
        {
            string sConnString = ConnectionString;
            _conn = new MySqlConnection(sConnString);
            _conn.Open();
        }

        public void DisconnectFromDB()
        {
            if (_conn!=null && _conn.State == ConnectionState.Open)
            {
                _conn.Close();
            }
        }

        public System.Data.DataTable GetAllTables()
        {
            ConnectToDB();
            DataTable dtTables = new DataTable();
            MySqlDataAdapter da = new MySqlDataAdapter();


            da.SelectCommand = new MySqlCommand("show tables", _conn);
            da.Fill(dtTables);
            DisconnectFromDB();
            return dtTables;
        }

        public List<string> GetTableName(string dbName)
        {

            var conn = GetConn();
            var sqlComm = new MySqlCommand("USE " + dbName + ";SHOW TABLES;", conn);

            sqlComm.CommandType = CommandType.Text;

            var sdaTables = new MySqlDataAdapter(sqlComm);

            DataTable dtTables = new DataTable();

            sdaTables.Fill(dtTables);

            DisconnectFromDB();
            List<string> s = new List<string>();

            foreach (DataRow dr in dtTables.Rows)
            {
                s.Add(dr[0].ToString());
            }
            return s;
        }

        public List<string> GetDataBaseName()
        {


            var conn = GetConn();
            var sqlComm = new MySqlCommand("SELECT SCHEMA_NAME FROM information_schema.SCHEMATA", conn);

            sqlComm.CommandType = CommandType.Text;

            var sdaTables = new MySqlDataAdapter(sqlComm);

            DataTable dtTables = new DataTable();

            sdaTables.Fill(dtTables);

            DisconnectFromDB();
            List<string> s = new List<string>();

            foreach (DataRow dr in dtTables.Rows)
            {
                s.Add(dr[0].ToString());
            }
            return s;
        }


        public List<string> GetAllDBName()
        {
            throw new Exception();
        }


        // 获取指定表的主键
        public DataTable GetPrimaryKeys(string sTableName)
        {
            //show index from UserConfigV2 where Key_name='PRIMARY'

            DataTable dtPkey = new DataTable("PrimaryKeys");
            string strSql = "show index from " + sTableName + " where Key_name='PRIMARY'";

            MySqlDataAdapter da = new MySqlDataAdapter();
            da.SelectCommand = new MySqlCommand(strSql, GetConn());
            da.Fill(dtPkey);
            return dtPkey;
        }


        public List<ETableInfo> GetColumns(string dataBaseName, string sTableName)
        {
            //string strSql = @"SHOW FULL COLUMNS FROM " + sTableName;

            string strSql = @"select  *  from information_schema.COLUMNS where TABLE_SCHEMA='" + dataBaseName + "' and   TABLE_NAME='" + sTableName + "'";

            // 获取字段
            DataTable dtColumn = new DataTable("Columns");
            MySqlDataAdapter da = new MySqlDataAdapter();
            da.SelectCommand = new MySqlCommand(strSql, GetConn());
            da.Fill(dtColumn);

            // 获取表的主键
            DataTable dtPkey = GetPrimaryKeys(sTableName);

            List<ETableInfo> list = new List<ETableInfo>();

            foreach (DataRow row in dtColumn.Rows)
            {


                ETableInfo entity = new ETableInfo();

                entity.ColumnName = row["Column_Name"].ToString();
                //entity.ColumnID = int.Parse(row["ColumnID"].ToString());
                entity.SystemTypeName = row["DATA_TYPE"].ToString();
               // entity.Precision = int.Parse(row["NUMERIC_PRECISION"].ToString());
               // entity.Scale = int.Parse(row["NUMERIC_SCALE"].ToString());
                //entity.MaxLength = row["CHARACTER_OCTET_LENGTH"] == null
                   // ? 0
                   // : int.Parse(row["CHARACTER_OCTET_LENGTH"].ToString());
                entity.Nullable = row["IS_NULLABLE"].ToString() == "YES" ? true : false;
                entity.Computed = false;
                entity.Identity = row["COLUMN_KEY"].ToString() == "PRI" ? true : false;
                entity.Description = row["COLUMN_COMMENT"].ToString() ?? "";
                entity.Default = row["COLUMN_DEFAULT"].ToString();
                entity.PrimaryKey = row["COLUMN_KEY"].ToString() == "PRI" ? true : false;
                entity.Remark = string.IsNullOrEmpty(row["COLUMN_COMMENT"].ToString()) == true ? entity.Remark = row["Column_Name"].ToString() : row["COLUMN_COMMENT"].ToString().Replace("\r\n", "");
                entity.Type = GetLanguageTypeName(entity.SystemTypeName);
                entity.DbType = GetDbTypeName(entity.SystemTypeName);
                list.Add(entity);


            }

            return list;
        }


        public string Building(BuilderType type)
        {
            string retVal = "";
            switch (type)
            {
                case BuilderType.Entity:
                    retVal = BuilderEntity();
                    break;
                case BuilderType.IRepository:
                    retVal = BuilderIRepository();
                    break;
                case BuilderType.IService:
                    retVal = BuilderIService();
                    break;
                case BuilderType.Mapping:
                    retVal = BuilderMap();
                    break;
                case BuilderType.Repository:
                    retVal = BuilderRepository();
                    break;
                case BuilderType.Service:
                    retVal = BuilderService();
                    break;
                case BuilderType.ServiceModel:
                    retVal = BuilderServiceModel();
                    break;
            }
            return retVal;
        }




        public string BuilderEntity()
        {


            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/DataEntity.vm");
            context.Put("list", ProjectInfo);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.EntitySavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.EntitySavePath + "/E" + ProjectInfo.TableName + ".cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }

            return writer.ToString();
        }


        public string BuilderMap()
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/Mapping.vm");
            context.Put("list", ProjectInfo);
            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.MapXmlSavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.MapXmlSavePath + "/" + ProjectInfo.TableName + ".xml", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }



            return writer.ToString();
        }


        public string BuilderIRepository()
        {

            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/IRepository.vm");
            context.Put("list", ProjectInfo);
            context.Put("StringHelper", new StringHelper());
            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.IRepositorySavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.IRepositorySavePath + "/I" + ProjectInfo.TableName + ".cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }


            return writer.ToString();
        }

        public string BuilderIService()
        {

            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/IService.vm");
            context.Put("list", ProjectInfo);
            context.Put("StringHelper", new StringHelper());
            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.IServiceSavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.IServiceSavePath + "/I" + ProjectInfo.TableName + "Service.cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }


            return writer.ToString();
        }


        public string BuilderService()
        {

            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/Service.vm");
            context.Put("list", ProjectInfo);
            context.Put("StringHelper", new StringHelper());
            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.ServiceSavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.ServiceSavePath + "/" + ProjectInfo.TableName + "Service.cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }


            return writer.ToString();
        }

        public string ConnectionString { get; set; }

        public EBuilderInfo BuilderInfo { get; set; }


        public string BuilderRepository()
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/Repository.vm");
            context.Put("list", ProjectInfo);
            context.Put("StringHelper", new StringHelper());
            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.RepositorySavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.RepositorySavePath + "/" + ProjectInfo.TableName + "Repository.cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }


            return writer.ToString();
        }


        public string BuilderServiceModel()
        {


            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/ServiceModel.vm");
            context.Put("list", ProjectInfo);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(ProjectInfo.ServiceModelSavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(ProjectInfo.ServiceModelSavePath + "/" + ProjectInfo.TableName + "Model.cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }

            return writer.ToString();
        }

        public string BuilderEntityToModel()
        {

            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/EntityToModel.vm");
            context.Put("list", ProjectInfo);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            return writer.ToString();

        }

        public string BuilderModelToEntity()
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/ModelToEntity.vm");
            context.Put("list", ProjectInfo);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            return writer.ToString();

        }

    }
}
